package com.guodi.common.utils;

import org.apache.commons.lang3.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class DateUtil {
    public static final String DATE_FORMAT_FULL = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE_FORMAT_SHORT_FULL = "yyyyMMddHHmmss";
    public static final String DATE_FORMAT_TIME = "HH:mm:ss";
    public static final String DATE_FORMAT_MON = "yyyy-MM";
    public static final String DATE_FORMAT_YMD = "yyyy-MM-dd";
    public static final String DATE_FORMAT_SHORT_YMD = "yyyyMMdd";
    public static final String DATE_FORMAT_BIAS_YMD = "yyyy/MM/dd";
    public static final String DATE_FORMAT_YMDH = "yyyy-MM-dd HH";
    public static final String DATE_FORMAT_YEAR = "yyyy";
    private static final SimpleDateFormat sdfYear = new SimpleDateFormat("yyyy");
    private static final SimpleDateFormat sdfDay = new SimpleDateFormat("yyyy-MM-dd");
    private static final SimpleDateFormat sdfDays = new SimpleDateFormat("yyyyMMdd");
    private static final SimpleDateFormat sdfTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static final SimpleDateFormat sdhTime = new SimpleDateFormat("yyyy-MM-dd HH");
    private static final SimpleDateFormat sdfTimes = new SimpleDateFormat("yyyyMMddHHmmss");

    public DateUtil() {
    }

    public static String getSdfTimes() {
        return sdfTimes.format(new Date());
    }

    public static String getYear() {
        return sdfYear.format(new Date());
    }

    public static String getDay() {
        return sdfDay.format(new Date());
    }

    public static String getDays() {
        return sdfDays.format(new Date());
    }

    public static String getTime() {
        return sdfTime.format(new Date());
    }

    public static String getTimeHour() {
        return sdhTime.format(new Date());
    }

    public static boolean compareDate(String s, String e) {
        if (parseDate(s, (String)null) != null && parseDate(e, (String)null) != null) {
            return parseDate(s, (String)null).getTime() >= parseDate(e, (String)null).getTime();
        } else {
            return false;
        }
    }

    public static Date parseDate(String date, String format) {
        if (StringUtils.isBlank(format)) {
            format = "yyyy-MM-dd";
        }

        SimpleDateFormat fmt = new SimpleDateFormat(format);

        try {
            return fmt.parse(date);
        } catch (ParseException var4) {
            var4.printStackTrace();
            return null;
        }
    }

    public static String formatDate(Date date, String fmtstr) {
        SimpleDateFormat fmt = new SimpleDateFormat(fmtstr);

        try {
            return fmt.format(date);
        } catch (Exception var4) {
            var4.printStackTrace();
            return null;
        }
    }

    public static boolean isValidDate(String s) {
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");

        try {
            fmt.parse(s);
            return true;
        } catch (Exception var3) {
            return false;
        }
    }

    public static int getDiffYear(String startTime, String endTime) {
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");

        try {
            int years = (int)((fmt.parse(endTime).getTime() - fmt.parse(startTime).getTime()) / 86400000L / 365L);
            return years;
        } catch (Exception var4) {
            return 0;
        }
    }

    public static long getDaySub(String beginDateStr, String endDateStr) {
        long day = 0L;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date beginDate = null;
        Date endDate = null;

        try {
            beginDate = format.parse(beginDateStr);
            endDate = format.parse(endDateStr);
        } catch (ParseException var8) {
            var8.printStackTrace();
        }

        day = (endDate.getTime() - beginDate.getTime()) / 86400000L;
        return day;
    }

    public static String getAfterDayDate(String days) {
        int daysInt = Integer.parseInt(days);
        Calendar canlendar = Calendar.getInstance();
        canlendar.add(5, daysInt);
        Date date = canlendar.getTime();
        SimpleDateFormat sdfd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateStr = sdfd.format(date);
        return dateStr;
    }

    public static String getAfterDayWeek(String days) {
        int daysInt = Integer.parseInt(days);
        Calendar canlendar = Calendar.getInstance();
        canlendar.add(5, daysInt);
        Date date = canlendar.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("E");
        String dateStr = sdf.format(date);
        return dateStr;
    }

    public static String getTimeByHour(int hour, String format) {
        if (StringUtils.isEmpty(format)) {
            format = "yyyy-MM-dd HH:mm:ss";
        }

        Calendar calendar = Calendar.getInstance();
        calendar.set(11, calendar.get(11) + hour);
        return (new SimpleDateFormat(format)).format(calendar.getTime());
    }

    public static String getTimeByMinute(int minute, String format) {
        if (StringUtils.isEmpty(format)) {
            format = "yyyy-MM-dd HH:mm:ss";
        }

        Calendar calendar = Calendar.getInstance();
        calendar.add(12, minute);
        return (new SimpleDateFormat(format)).format(calendar.getTime());
    }

    public static String getTimeByDay(int day, String format) {
        if (StringUtils.isEmpty(format)) {
            format = "yyyy-MM-dd HH:mm:ss";
        }

        Calendar calendar = Calendar.getInstance();
        calendar.add(5, day);
        return (new SimpleDateFormat(format)).format(calendar.getTime());
    }

    public static List<Date> getDatesBetweenTwoDate(Date beginDate, Date endDate, int field) {
        List<Date> lDate = new ArrayList();
        lDate.add(beginDate);
        Calendar cal = Calendar.getInstance();
        cal.setTime(beginDate);
        boolean bContinue = true;

        while(bContinue) {
            cal.add(field, 1);
            if (!endDate.after(cal.getTime())) {
                break;
            }

            lDate.add(cal.getTime());
        }

        lDate.add(endDate);
        return lDate;
    }

    public static String getHour(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        String hour = cal.get(11) + "";
        if (hour.length() == 1) {
            hour = "0" + hour;
        }

        return hour;
    }

    public static String getDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        String day = cal.get(5) + "";
        if (day.length() == 1) {
            day = "0" + day;
        }

        return day;
    }

    public static Date setEndDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(11, 23);
        cal.set(12, 59);
        cal.set(13, 59);
        return cal.getTime();
    }



    public static String getDatePoor(Date endDate, Date nowDate) {
        long nd = 86400000L;
        long nh = 3600000L;
        long nm = 60000L;
        long ns = 1000L;
        long diff = endDate.getTime() - nowDate.getTime();
        long day = diff / nd;
        long hour = diff % nd / nh;
        long min = diff % nd % nh / nm;
        long sec = diff % nd % nh % nm / ns;
        StringBuffer buffer = new StringBuffer();
        if (day != 0L) {
            buffer.append(day + "天");
            buffer.append(hour + "小时");
            buffer.append(min + "分钟");
            buffer.append(sec + "秒");
        } else if (hour != 0L) {
            buffer.append(hour + "小时");
            buffer.append(min + "分钟");
            buffer.append(sec + "秒");
        } else if (min != 0L) {
            buffer.append(min + "分钟");
            buffer.append(sec + "秒");
        } else {
            buffer.append(sec + "秒");
        }

        return buffer.toString();
    }

    /**
     * 获取上一个时间节点，如果是年，获取上一年；如果是月，获取上一个月；如果是季度，获取上一季度
     * @param queryTime 年：2020；月：2020-01；季度：2020-1
     * @return  上一个时间节点，如果是年，获取上一年；如果是月，获取上一个月；如果是季度，获取上一季度
     *          (2020) ==> 2019; (2020-09) ==> 2020-08; (2020-2) ==> 2020-1
     * @author 陈宏成
     * @date 2021/10/27
     * */
    public static String getLastTimePoint(String queryTime){
        if(queryTime.length() == 4){
            // 年
            Integer lastYear = Integer.valueOf(queryTime.trim()) - 1;
            return lastYear.toString();
        }else if(queryTime.length() == 6){
            // 季度
            String[] split = queryTime.split("-");
            if (Objects.equals(split[1], "1")){
                Integer lastYear = Integer.valueOf(split[0]) - 1;
                return lastYear.toString() + "-4";
            }
            Integer lastQuarter = Integer.valueOf(split[1]) - 1;
            return split[0] + "-" + lastQuarter;
        }else if(queryTime.length() == 7){
            // 月度
            String[] split = queryTime.split("-");
            if (Objects.equals(split[1], "01")){
                Integer lastYear = Integer.valueOf(split[0]) - 1;
                return lastYear.toString() + "-12";
            }
            Integer lastMonth = Integer.valueOf(split[1]) - 1;
            if (lastMonth < 10){
                return split[0] + "-0" + lastMonth;
            }else{
                return split[0] + "-" + lastMonth;
            }
        }
        throw new RuntimeException("queryTime时间格式错误");
    }

    /**
     * 填充时间列表，queryTimeBegin和queryTimeEnd的时间格式必须相同
     * @param queryTimeBegin 开始时间，年：2020；月：2020-09；季度：2020-1
     * @param queryTimeEnd   结束时间，年：2020；月：2020-09；季度：2020-1
     * @return (2015,2018) ==> [2015,2016,2017,2018];
     *         (2020-05,2020-07) ==> [2020-05,2020-06,2020-07]
     *         (2020-1,2020-3) ==> [2020-1,2020-2,2020-3]
     * @author 陈宏成
     * @date 2021/10/27
     * */
    public static List<String> fillTimeList(String queryTimeBegin, String queryTimeEnd){
        HashSet<String> resultset = new HashSet<>();
        if(queryTimeBegin.length() != queryTimeEnd.length()){
            throw new RuntimeException("queryTimeBegin 和 queryTimeEnd 时间格式不一致");
        } else if(queryTimeBegin.length() == 4){
            // 年
            int startYearI = Integer.parseInt(queryTimeBegin);
            int endYearI = Integer.parseInt(queryTimeEnd);

            if (startYearI > endYearI){
                throw new RuntimeException("queryTimeBegin 不能大于 queryTimeEnd");
            }else{
                for(; startYearI <= endYearI; startYearI++) {
                    resultset.add(String.valueOf(startYearI));
                }
            }
        }else if(queryTimeBegin.length() == 6){
            // 季度
            String[] beginSplit = queryTimeBegin.split("-");
            String[] endSplit = queryTimeEnd.split("-");
            int beginYear = Integer.parseInt(beginSplit[0]);
            int beginQuarter = Integer.parseInt(beginSplit[1]);
            int endYear = Integer.parseInt(endSplit[0]);
            int endQuarter = Integer.parseInt(endSplit[1]);
            if(beginYear > endYear || (beginYear == endYear && beginQuarter > endQuarter)){
                throw new RuntimeException("queryTimeBegin 不能大于 queryTimeEnd");
            }
            for(int i = beginYear ; i <= endYear; i++){
                int j = i == beginYear? beginQuarter: 1;
                for(;(i == endYear && j <= endQuarter) || ((i < endYear && j <= 4)); j++){
                    resultset.add(i + "-" + j);
                }
            }
        }else if(queryTimeBegin.length() == 7){
            String[] beginSplit = queryTimeBegin.split("-");
            String[] endSplit = queryTimeEnd.split("-");
            int beginYear = Integer.parseInt(beginSplit[0]);
            int beginMonth = Integer.parseInt(beginSplit[1]);
            int endYear = Integer.parseInt(endSplit[0]);
            int endMonth = Integer.parseInt(endSplit[1]);
            if(beginYear > endYear || (beginYear == endYear && beginMonth > endMonth)){
                throw new RuntimeException("queryTimeBegin 不能大于 queryTimeEnd");
            }
            for(int i = beginYear ; i <= endYear; i++){
                int j = i == beginYear? beginMonth: 1;
                for(;(i == endYear && j <= endMonth) || ((i < endYear && j <= 12)); j++){
                    if (j < 10){
                        resultset.add(i + "-0" + j);
                    }else{
                        resultset.add(i + "-" + j);
                    }
                }
            }
        }
        return new ArrayList<>(resultset);
    }
}
